<template>
	<div class="main" style="display: flex;justify-content: center; align-items: center; overflow: hidden;">
		<template v-if="action=='direct'">
			<div style="text-align: center" ref="scrollDiv" v-if="direct.knowledgePointsNo">
				<div ref="chartRef" class="chart-container"></div>
				<el-form :inline="true" ref="formRef" :model="form" label-width="220px">
					<el-form-item prop="chartName"
								  :rules="{required: true, message: '请输入知识关联图谱名称', trigger: 'change'}">
						<el-input placeholder="请输入知识关联图谱名称" @change="submitForm" v-model.trim="form.chartName" />
					</el-form-item>
					<el-form-item>
						<!--			<el-button type="text" @click="submitForm">确定</el-button>
									<el-button type="text" @click="upForm">{{btnTitle}}</el-button>-->
						<el-switch
							v-model="upValue"
							@change="upForm"
							size="large"
							active-text="上架"
							inactive-text="下架"
						/>
					</el-form-item>
				</el-form>
			</div>
			<el-empty v-else description="暂无知识关联图谱数据" />
		</template>
		<template v-else>
			<div style="text-align: center" ref="scrollDiv">
				<div ref="chartRef" class="chart-container"></div>
			</div>
		</template>
	</div>
</template>

<script setup lang="ts">
import * as echarts from 'echarts';
import { ref, onMounted, onUnmounted, nextTick, reactive } from 'vue';
import { getKnowledgePointsChart, namePointsChart, upAndDownPointsChart } from '/@/api/knowledge/index';
import { ElMessage } from 'element-plus';
import dagre from 'dagre'; // 引入 dagre 布局库

const chartRef = ref<HTMLElement | null>(null);
let myChart: echarts.ECharts | null = null;
let data = ref([]);
let upValue = ref(false);
let btnTitle = ref('');

let links = ref([]);
const scrollDiv = ref(null);
const props = defineProps({
	direct: {
		type: Object,
		default: () => ({})
	},
	action: {
		type: String
	}
});
let form = reactive({
	"chartName": props.direct.chartName,
	"pointsNO": Number(props.direct.knowledgePointsNo)
});

const submitForm = () => {
	if (form.chartName) {
		namePointsChart(form.chartName, form.pointsNO);
	}
};

const upForm = async () => {
	let res = await upAndDownPointsChart(form.pointsNO);
	if (res.code == 200) {
		let title = upValue.value?'上架':'下架';
		ElMessage.success( title + '成功');
	}
};

// 使用 dagre 计算树形布局
const computeTreeLayout = (nodes: any[], edges: any[]) => {
	const g = new dagre.graphlib.Graph();
	g.setGraph({
		rankdir: 'TB', // 垂直方向布局（Top to Bottom）
		nodesep: 50,   // 节点水平间距
		ranksep: 100,  // 层级垂直间距
		align: 'UL',   // 对齐方式（左上对齐）
	});
	g.setDefaultEdgeLabel(() => ({}));

	// 添加节点（需指定宽高，dagre 用其计算布局）
	nodes.forEach(node => {
		g.setNode(node.id, { width: 60, height: 30 });
	});

	// 添加边
	edges.forEach(edge => {
		g.setEdge(edge.source, edge.target);
	});

	// 计算布局
	dagre.layout(g);

	const nodeDepths: Record<string, number> = {};
	const calculateDepth = (nodeId: string): number => {
		if (nodeDepths[nodeId] !== undefined) return nodeDepths[nodeId];

		const incomingEdges = edges.filter(edge => edge.target === nodeId);
		if (incomingEdges.length === 0) {
			nodeDepths[nodeId] = 0;
			return 0;
		}

		const depths = incomingEdges.map(edge => calculateDepth(edge.source) + 1);
		const maxDepth = Math.max(...depths);
		nodeDepths[nodeId] = maxDepth;
		return maxDepth;
	};

	nodes.forEach(node => {
		calculateDepth(node.id);
	});
	// 更新节点坐标
	nodes.forEach((node, index) => {
		const dagreNode = g.node(node.id);
		node.x = dagreNode.x;
		node.y = dagreNode.y;
		// 固定坐标（避免力导向干扰）
		node.fixed = true;
		const originalLevel = (nodeDepths[node.id] || 0) + 1;
		if (originalLevel === 1) {
			node.itemStyle = {
				color: '#bc2cec',
				borderWidth: 2
			};
			node.label = {
				show: true,
				formatter: [
					`{a|${node.name}}`,
					`{b|ladder: ${node.ladder}}`
				].join('\n'),
				rich: {
					a: {
						fontSize: 12,
						textShadowBlur: 2,
						textShadowColor: 'rgba(255,255,255,0.5)'
					},
					b: {
						fontSize: 12,
						align: 'center',textShadowBlur: 2,
						textShadowColor: 'rgba(255,255,255,0.5)'
					}
				}
			};
		} else {
			node.itemStyle = {
				color: '#416af5',
				borderWidth: 2
			};
			node.label = {
				show: true,
				formatter: [
					`{a|${node.name}}`,
					`{b|ladder: ${node.ladder}}`
				].join('\n'),
				rich: {
					a: {
						fontSize: 12,
						textShadowBlur: 2,
						textShadowColor: 'rgba(255,255,255,0.5)'
					},
					b: {
						fontSize: 12,
						align: 'center',textShadowBlur: 2,
						textShadowColor: 'rgba(255,255,255,0.5)'
					}
				}
			};
		}

	});

	return { nodes, edges };
};

onMounted(async () => {
	await nextTick(() => {
		let scrollElem = scrollDiv.value;
		scrollElem?.scrollTo({ top: 10000, behavior: 'smooth' });
	});

	if (props.direct.knowledgePointsNo) {
		upValue.value = (props.direct.chartStatus == 1) ?  true: false;
		let res = await getKnowledgePointsChart(props.direct.knowledgePointsNo);
		await nextTick();
		const container = chartRef.value;

		if (container) {
			// 预处理数据
			data.value = res.data.data.map(item => ({
				...item,
				id: item.knowledgePointsNo.toString(),
				name: item.name || `Node ${item.knowledgePointsNo}`,
			}));

			links.value = res.data.link.map(item => ({
				...item,
				source: item.from.toString(),
				target: item.to.toString(),
				symbol: ['none', 'arrow'], // 箭头指向目标节点
				lineStyle: {
					width: 2,
					curveness: 0.2, // 轻微弯曲避免直线重叠
				},
			}));

			// 计算树形布局
			const { nodes, edges } = computeTreeLayout(data.value, links.value);

			// 初始化图表
			myChart = echarts.init(container);
			const option = {
				tooltip: {},
				animationDuration: 1500,
				animationEasingUpdate: 'quinticInOut',
				series: [{
					type: 'graph',
					layout: 'none',
					data: nodes,
					links: edges,
					symbolSize: 45,
					roam: true,
					// 修改这里的 label 配置
					label: {
						show: true,
						position: 'inside',
						formatter: (params: any) => {
							return params.data.label?.formatter || params.data.name;
						},
						rich: nodes[0]?.label?.rich || {} // 使用节点中定义的 rich 样式
					},
					edgeSymbol: ['none', 'arrow'],
					edgeSymbolSize: [0, 10],
					edgeLabel: {
						show: false,
					},
					lineStyle: {
						width: 2,
						curveness: 0.2,
						opacity: 0.9,
					},
					emphasis: {
						focus: 'adjacency',
						lineStyle: {
							width: 3,
						},
					},
				}],
			};

			myChart.setOption(option);
			/*myChart?.on('click', function (params) {
				if (params.componentType === 'series') {
					alert('你点击了 ' + params.name + ', 数据索引为 ' + params.dataIndex);
				}
			});*/

			// 响应式适配
			const resizeHandler = () => {
				if (myChart) {
					myChart.resize();
				}
			};
			window.addEventListener('resize', resizeHandler);

			onUnmounted(() => {
				if (myChart) myChart.dispose();
				window.removeEventListener('resize', resizeHandler);
			});
		}
	} else {
		const container = chartRef.value;
		if (container) {

			// 预处理数据
			data.value = props.direct.data.map(item => ({
				...item,
				id: item.knowledgePointsNo.toString(),
				name: item.name || `Node ${item.knowledgePointsNo}`,
			}));

			links.value = props.direct.link.map(item => ({
				...item,
				source: item.from.toString(),
				target: item.to.toString(),
				symbol: ['none', 'arrow'], // 箭头指向目标节点
				lineStyle: {
					width: 2,
					curveness: 0.2, // 轻微弯曲避免直线重叠
				},
			}));

			// 计算树形布局
			const { nodes, edges } = computeTreeLayout(data.value, links.value);

			// 初始化图表
			myChart = echarts.init(container);
			const option = {
				tooltip: {},
				animationDuration: 1500,
				animationEasingUpdate: 'quinticInOut',
				series: [{
					type: 'graph',
					layout: 'none',
					data: nodes,
					links: edges,
					symbolSize: 45,
					roam: true,
					// 修改这里的 label 配置
					label: {
						show: true,
						position: 'inside',
						formatter: (params: any) => {
							return params.data.label?.formatter || params.data.name;
						},
						rich: nodes[0]?.label?.rich || {} // 使用节点中定义的 rich 样式
					},
					edgeSymbol: ['none', 'arrow'],
					edgeSymbolSize: [0, 10],
					edgeLabel: {
						show: false,
					},
					lineStyle: {
						width: 2,
						curveness: 0.2,
						opacity: 0.9,
					},
					emphasis: {
						focus: 'adjacency',
						lineStyle: {
							width: 3,
						},
					},
				}],
			};

			myChart.setOption(option);
			/*myChart?.on('click', function (params) {
				if (params.componentType === 'series') {
					alert('你点击了 ' + params.name + ', 数据索引为 ' + params.dataIndex);
				}
			});*/

			// 响应式适配
			const resizeHandler = () => {
				if (myChart) {
					myChart.resize();
				}
			};
			window.addEventListener('resize', resizeHandler);

			onUnmounted(() => {
				if (myChart) myChart.dispose();
				window.removeEventListener('resize', resizeHandler);
			});
		}
	}
});
</script>

<style scoped>
.chart-container {
	width: 100%;
	min-width: 230px;
	height: 600px;
	border: 0;
	margin-bottom: 26px;
}
</style>
